package com.zyl.blog.service;/**
 * @author 14323
 * @date 2020/8/9 10:15
 */

import com.zyl.blog.NotFoundException;
import com.zyl.blog.dao.BlogRepository;
import com.zyl.blog.pojo.Blog;
import com.zyl.blog.pojo.Tag;
import com.zyl.blog.pojo.Type;
import com.zyl.blog.util.MarkDownUtils;
import com.zyl.blog.vo.BlogQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.*;

/**
 * @Description: TODO
 * @author: scott
 * @date: 2020年08月09日 10:15
 */
@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    private BlogRepository blogRepository;

    @Override
    public Blog getBlog(Long id) {
        return blogRepository.findById(id).get();
    }

    @Override
    public Blog getAndConvert(Long id) {
        Blog blog = blogRepository.findById(id).get();
        if (blog == null) {
            throw new NotFoundException("该博客不存在");
        }
        //得到博客内容
        String content = blog.getContent();
        //new一个新的Blog，以防Hibernate更新当前Blog对象的内容
        Blog htmlBlog = new Blog();
        //将当前对象copy到一个新的Blog对象中后再修改它的内容为html格式
        BeanUtils.copyProperties(blog, htmlBlog);
        htmlBlog.setContent(MarkDownUtils.markdownToHtmlExtensions(content));
        //浏览次数加一
        blogRepository.updateViews(id);
        return htmlBlog;
    }

    @Override
    public Page<Blog> getBlogPage(Pageable pageable, BlogQuery blogQuery) {

        return blogRepository.findAll(
                new Specification<Blog>() {
                    @Override
                    public Predicate toPredicate(Root<Blog> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                        List<Predicate> predicates = new ArrayList<>();
                        if (!"".equals(blogQuery.getTitle()) && blogQuery.getTitle() != null) {
                            predicates.add(cb.like(root.get("title"), "%" + blogQuery.getTitle() + "%"));
                        }
                        if (blogQuery.getTypeId() != null) {
                            predicates.add(cb.equal(root.<Type>get("type").get("id"), blogQuery.getTypeId()));
                        }
                        if (blogQuery.isRecommend()) {
                            predicates.add(cb.equal(root.<Boolean>get("recommend"), blogQuery.isRecommend()));
                        }
                        cq.where(predicates.toArray(new Predicate[predicates.size()]));
                        return null;
                    }
                }, pageable);
    }

    @Override
    public Page<Blog> getBlogPage(Pageable pageable) {
        return blogRepository.findAll(pageable);
    }

    @Override
    public Page<Blog> getBlogPage(Long tagId, Pageable pageable) {

        return blogRepository.findAll(new Specification<Blog>() {
            @Override
            public Predicate toPredicate(Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                Join join = root.join("tags");

                return criteriaBuilder.equal(join.get("id"), tagId);

            }
        }, pageable);
    }

    @Override
    public Page<Blog> getSearchBlogPage(String query, Pageable pageable) {

        return blogRepository.findByQuery(query, pageable);
    }

    @Override
    public Page<Blog> getTopBlog(Integer size) {
        Sort sort = Sort.by(Sort.Direction.DESC, "updateTime");
        Pageable pageable = PageRequest.of(0, size, sort);
        return blogRepository.findAll(pageable);
    }

    @Override
    public Map<String, List<Blog>> archiveBlog() {
        List<String> years = blogRepository.findGroupYear();
        Map<String, List<Blog>> map = new LinkedHashMap<>();
        for (String year : years) {
            map.put(year, blogRepository.findByYear(year));
        }
        return map;
    }

    @Override
    public Long countBlog() {
        return blogRepository.count();
    }

    @Transactional
    @Override
    public Blog saveBlog(Blog blog) {
        if (blog.getId() == null){
            //新增
            blog.setCreateTime(new Date());
            blog.setUpdateTime(new Date());
            blog.setViews(0);
        } else {
            //更新
            blog.setUpdateTime(new Date());
        }
        return blogRepository.save(blog);
    }

    @Transactional
    @Override
    public Blog updateBlog(Long id, Blog blog) {
        Blog b = blogRepository.findById(id).get();
        if (b == null) {
            throw new NotFoundException("该博客不存在");
        }
        BeanUtils.copyProperties(blog, b, "createTime");
        b.setUpdateTime(new Date());

        return blogRepository.save(b);
    }

    @Transactional
    @Override
    public void deleteBlog(Long id) {
        blogRepository.deleteById(id);
    }
}
